/*
Copyright (C) 2011 Salil Bhagurkar

This file is part of illusion

illusion is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

illusion is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with illusion.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <kernel/console.h>

#define BIT_DIV (8 * sizeof(u32))

int get_bit(void *bitmap, uint_t nr)
{
	uint_t i = nr / BIT_DIV;
	uint_t bit = nr % BIT_DIV;
	return (((u32 *)bitmap)[i] & (1UL << bit)) ? 1 : 0;
}

void set_bit(void *bitmap, uint_t nr)
{
	uint_t i = nr / BIT_DIV;
	uint_t bit = nr % BIT_DIV;
	((u32 *)bitmap)[i] |= (1UL << bit);
}

void clear_bit(void *bitmap, uint_t nr)
{
	uint_t i = nr / BIT_DIV;
	uint_t bit = nr % BIT_DIV;
	((u32 *)bitmap)[i] &= ~(1UL << bit);
}


//TODO Optimize this by skipping fully cleared/set dwords
int find_set_bit(void *bitmap, uint_t nr, uint_t *location)
{
	uint_t i;
	for(i = 0; i < nr; i++) {
		if(get_bit(bitmap, i)) {
			*location = i;
			return 0;
		}
	}
	return -1;
}

int find_clear_bit(void *bitmap, uint_t nr, uint_t *location)
{
	uint_t i;
	for(i = 0; i < nr; i++) {
		if(!get_bit(bitmap, i)) {
			*location = i;
			return 0;
		}
	}
	return -1;
}

uint_t count_set_bit(void *bitmap, uint_t nr)
{
	uint_t i;
	uint_t count = 0;
	for(i = 0; i < nr; i++) {
		if(get_bit(bitmap, i))
			count++;
	}
	return count;
}

uint_t count_clear_bit(void *bitmap, uint_t nr)
{
	uint_t i;
	uint_t count = 0;
	for(i = 0; i < nr; i++) {
		if(!get_bit(bitmap, i))
			count++;
	}
	return count;
}
